package com.cw.jeeyt.service.aspect;

import java.lang.reflect.Method;
import java.util.Collection;
import java.util.Date;

import org.aspectj.lang.JoinPoint;
import org.aspectj.lang.annotation.After;
import org.aspectj.lang.annotation.Aspect;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;

import com.alibaba.fastjson.JSON;
import com.cw.jeeyt.common.annotation.LogParam;
import com.cw.jeeyt.service.bo.security.SecurityOperateLogBo;
import com.cw.jeeyt.service.bo.security.SecurityUserBo;
import com.cw.jeeyt.core.util.SessionUtil;
import com.cw.jeeyt.service.intf.security.SecurityOperateLogService;
import com.cw.lang.common.utils.IdGenerator;

@Aspect
@Service
public class LogAspect {
    private Logger logger = LoggerFactory.getLogger(LogAspect.class);
    //操作日志业务接口
    @Autowired
    private SecurityOperateLogService securityOperateLogService;

    /**
     * 记录操作类日志
     *
     * @param jp
     */
    @After("execution(* com.cw.jeeyt..dao.*.*(..))")
    public void addOperateLogFromDAO(JoinPoint jp) {

        String targetMethodName = jp.getSignature()
            .getName();

        Class<?> daoInterface = null;
        LogParam logParam = null;
        for (Class<?> iface : jp.getTarget()
            .getClass()
            .getInterfaces()) {
            try {
                for (Method method : iface.getDeclaredMethods()) {
                    if (method.getName()
                        .equals(targetMethodName)) {
                        if (method.isAnnotationPresent(LogParam.class)) {
                            logParam = method.getAnnotation(LogParam.class);
                            daoInterface = iface;
                            break;
                        }
                    }
                }
            } catch (Exception e) {
                logger.error(iface + "中没有目标方法(logAspect)", e);
            }
        }

        if (logParam != null) {
            saveLogOperator(jp, targetMethodName, daoInterface, logParam);
        }
    }

    private void saveLogOperator(JoinPoint jp, String targetMethodName, Class<?> daoInterface, LogParam logParam) {
        SecurityUserBo securityUserVo = SessionUtil.getSessionUser();
        if (securityUserVo == null) {
            securityUserVo = new SecurityUserBo();
            securityUserVo.setUsername("系统后台");
        }
        Long userId = securityUserVo.getId();
        String userName = securityUserVo.getUsername();
        // 切面方法参数
        Object[] paramList = jp.getArgs();
        String params = parseParames(paramList);
        String className = daoInterface.getName();
        String operateModule = logParam.operateModule();
        String logDesc = logParam.logDes();

        String uuid = IdGenerator.nextStrId();
        SecurityOperateLogBo logOperate = new SecurityOperateLogBo();
        logOperate.setId(IdGenerator.nextStrId());
        if (userId == null) {
            logOperate.setUserId("100");
        } else {
            logOperate.setUserId(userId.toString());
        }
        logOperate.setUserName(userName);
        logOperate.setOperateType(targetMethodName);
        logOperate.setOperateModule(operateModule + ":" + className + "." + targetMethodName);
        logOperate.setLogDes(logDesc + params);
        logOperate.setLogDate(new Date());

        try {
            securityOperateLogService.insert(logOperate);
        } catch (Exception e) {
            logger.error("从DAO接口添加操作日志时出错！", e);
        }
        logger.info(logDesc);
    }

    /**
     * 解析方法参数
     *
     * @param parames 方法参数
     * @return 解析后的方法参数
     */
    private String parseParames(Object[] parames) {
        StringBuffer sb = new StringBuffer();
        for (int i = 0; i < parames.length; i++) {
            if (parames[i].getClass()
                .getName()
                .indexOf("com.cw") != -1) {
                if (parames[i] instanceof Object[] || parames[i] instanceof Collection) {
                    String str = JSON.toJSONString(parames[i]);
                    if (str.length() > 1000) {
                        str = str.substring(0, 1000);
                    }
                    if (i == parames.length - 1) {
                        sb.append(str);
                    } else {
                        sb.append(str + ",");
                    }
                } else {
                    String json = JSON.toJSONString(parames[i]);
                    if (json.length() > 1000) {
                        json = json.substring(0, 1000);
                    }
                    if (i == parames.length - 1) {
                        sb.append(json);
                    } else {
                        sb.append(json + ",");
                    }
                }

            } else if (parames[i] instanceof String) {
                if (i == parames.length - 1) {
                    sb.append(parames[i]);
                } else {
                    sb.append(parames[i] + ",");
                }
            } else if (parames[i] instanceof Object[] || parames[i] instanceof Collection) {
                String str = JSON.toJSONString(parames[i]);
                if (str.length() > 1000) {
                    str = str.substring(0, 1000);
                }
                if (i == parames.length - 1) {
                    sb.append(str.toString());
                } else {
                    sb.append(str.toString() + ",");
                }
            }

        }
        String params = sb.toString();
        params = params.replaceAll("(\"\\w+\":\"\",)", "");
        params = params.replaceAll("(,\"\\w+\":\"\")", "");
        params = params.replaceAll("\"", "");
        return params;
    }
}
